home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 2010 April
/
PCWorld0410.iso
/
pluginy Firefox
/
684
/
684.xpi
/
chrome
/
fireftp.jar
/
content
/
js
/
remote
/
remoteDirTree.js
next >
Wrap
Text File
|
2008-06-14
|
24KB
|
605 lines
var remoteDirTree = {
data : new Array(),
rowCount : 0,
extraCallback : null,
dirtyList : new Array(),
ignoreSelect : false,
getCellText : function(row, column) { return this.data[row].leafName; },
getLevel : function(row) { return this.data[row].level; },
getParentIndex : function(row) { return this.data[row].parentIndex; },
getImageSrc : function(row, col) { },
getColumnProperties : function(colid, col, props) { },
getRowProperties : function(row, props) { },
hasNextSibling : function(row, nextrow) { return this.data[row].hasNext; },
isContainer : function(row) { return true; },
isContainerEmpty : function(row) { return this.data[row].empty; },
isContainerOpen : function(row) { return this.data[row].open; },
isSeparator : function(row) { return false; },
isSorted : function(row) { return false; },
setTree : function(treebox) { this.treebox = treebox; },
getCellProperties : function(row, col, props) {
if (row >= 0 && row < this.data.length && this.data[row]) {
if (!gFtp.isConnected) {
props.AppendElement(gAtomService.getAtom("disconnected"));
}
if (this.data[row].isHidden) {
props.AppendElement(gAtomService.getAtom("hidden"));
}
}
},
toggleOpenState : function(row, suppressChange) {
if (!gFtp.isConnected || gFtp.isListing()) {
return;
}
if (this.isContainerOpen(row)) {
var level = this.data[row].level;
var lastChild = row;
while (lastChild + 1 < this.rowCount && this.data[lastChild + 1].level > level) { // find last index in same level as collapsed dir
++lastChild;
}
this.data[row].children = this.data.splice(row + 1, lastChild - row); // get rid of subdirectories from view
this.updateParentIndices();
this.rowCount = this.data.length;
this.treebox.rowCountChanged(row, -(lastChild - row));
this.data[row].open = false;
this.treebox.invalidateRow(row); // update row
var remotePathSlash = gRemotePath.value + (gRemotePath.value.charAt(gRemotePath.value.length - 1) != "/" ? "/" : '');
var dataPathSlash = this.data[row].path + (this.data[row].path.charAt(this.data[row].path.length - 1) != "/" ? "/" : '');
if (remotePathSlash.indexOf(dataPathSlash) == 0 && gRemotePath.value != this.data[row].path
&& gRemotePath.value.match(/\x2f/g).length > this.data[row].level && !suppressChange) {
gRemotePath.value = this.data[row].path; // we were in a subdirectory and we collapsed
this.selection.select(row);
this.treebox.ensureRowIsVisible(row);
remoteTree.updateView();
} else if (gRemotePath.value == this.data[row].path) {
this.selection.select(row);
this.treebox.ensureRowIsVisible(row);
}
this.horizontalScroll(false, row);
} else {
for (var x = 0; x < this.dirtyList.length; ++x) { // see if the row is dirty
if (this.dirtyList[x] == this.data[row].path) {
this.dirtyList.splice(x, 1);
this.data[row].children = null;
break;
}
}
if (this.data[row].children) { // see if any of the rows children are dirty
for (var x = 0; x < this.dirtyList.length; ++x) {
var found = false;
for (var y = this.data[row].children.length - 1; y >= 0; --y) {
if (this.data[row].children[y].path == this.dirtyList[x]) {
found = true;
this.data[row].children[y].children = null;
this.data[row].children[y].open = false;
this.data[row].children[y].empty = false;
} else if (this.data[row].children[y].path.indexOf(this.dirtyList[x]
+ (this.dirtyList[x].charAt(this.dirtyList[x].length - 1) != "/" ? "/" : '')) == 0) {
found = true;
this.data[row].children.splice(y, 1);
}
}
if (found) {
this.dirtyList.splice(x, 1);
}
}
}
if (this.data[row].children) { // stored from before
for (var x = this.data[row].children.length - 1; x >= 0; --x) {
this.data.splice(row + 1, 0, this.data[row].children[x]);
}
this.updateParentIndices();
this.rowCount = this.data.length;
this.treebox.rowCountChanged(row + 1, this.data[row].children.length);
this.data[row].children = null;
this.data[row].open = true;
this.treebox.invalidateRow(row);
this.horizontalScroll(true, row);
} else {
gFtp.list(this.data[row].path, "remoteDirTree.toggleOpenState2(" + row + ")", false); // get data for this directory
}
}
},
toggleOpenState2 : function(row) {
var newDirectories = new Array();
for (var x = 0; x < gFtp.listData.length; ++x) { // pick out the directories
if (gFtp.listData[x].isDirectory()) {
newDirectories.push(gFtp.listData[x]);
}
}
if (newDirectories.length == 0) { // no subdirectories
this.data[row].empty = true;
this.data[row].open = false;
} else { // has subdirectories
for (var x = 0; x < newDirectories.length; ++x) {
var path = gFtp.constructPath(this.data[row].path, newDirectories[x].leafName);
var parentDir = this.data[row].path;
newDirectories[x] = { open : false,
empty : false,
hasNext : true,
parentIndex : -1,
children : null,
path : path,
leafName : newDirectories[x].leafName,
parent : parentDir,
level : path.match(/\x2f/g).length,
sortPath : path.replace(/\x2f/g, "\x01").toLowerCase(),
isHidden : newDirectories[x].isHidden };
}
newDirectories.sort(directorySort);
newDirectories[newDirectories.length - 1].hasNext = false; // last one doesn't have a next
for (var x = newDirectories.length - 1; x >= 0; --x) {
this.data.splice(row + 1, 0, newDirectories[x]);
}
this.updateParentIndices();
this.rowCount = this.data.length;
this.treebox.rowCountChanged(row + 1, newDirectories.length);
this.data[row].open = true;
}
this.treebox.invalidateRow(row);
this.horizontalScroll(true, row);
if (this.updateViewAfter) {
this.updateViewAfter = false;
remoteTree.updateView2();
}
if (this.extraCallback) {
var tempCallback = this.extraCallback;
this.extraCallback = null;
tempCallback();
}
},
horizontalScroll : function(doOpen, row) { // horizontal scrollbars, baby!
$('remotedirname').removeAttribute('flex');
var max = 125;
for (var z = 0; z < this.rowCount; ++z) { // this is what we CS folk like to call a TOTAL HACK
var x = { }; var y = { }; var width = { }; var height = { }; // but, hey, it works so bite me
this.treebox.getCoordsForCellItem(z, this.treebox.columns["remotedirname"], "text", x, y, width, height);
if (x.value + width.value + 125 > max) {
max = x.value + width.value + 125;
}
}
//if (doOpen) {
this.readjustHorizontalPosition(row);
//}
$('remotedirname').setAttribute('width', max);
},
readjustHorizontalPosition : function(row) {
var x = { }; var y = { }; var width = { }; var height = { };
var first = this.treebox.getFirstVisibleRow() > 0 ? this.treebox.getFirstVisibleRow() : 0;
var last = this.treebox.getLastVisibleRow() - 1 >= 0 ? this.treebox.getLastVisibleRow() - 1 : 0;
this.treebox.getCoordsForCellItem(row != -1 ? row : 0, this.treebox.columns["remotedirname"], "text", x, y, width, height);
this.treebox.scrollToHorizontalPosition(this.treebox.horizontalPosition + x.value - 60 >= 0 ? this.treebox.horizontalPosition + x.value - 60 : 0);
var self = this;
var func = function() {
self.treebox.ensureRowIsVisible(last);
self.treebox.ensureRowIsVisible(first);
};
if (first < this.data.length) {
setTimeout(func, 0);
}
},
addDirtyList : function(path) {
gFtp.removeCacheEntry(path);
for (var x = 0; x < this.dirtyList.length; ++x) {
if (this.dirtyList[x] == path) {
return;
}
}
this.dirtyList.push(path);
},
updateParentIndices : function() {
for (var x = 0; x < this.data.length; ++x) {
this.data[x].parentIndex = this.indexOfPath(this.data[x].parent); // ah, beautiful
}
},
indexOfPath : function(path) { // binary search to find a path in the remoteDirTree
if (!path) {
return -1;
}
var left = 0;
var right = this.data.length - 1;
var origPath = path;
path = path.replace(/\x2f/g, "\x01").toLowerCase();
while (left <= right) {
var mid = Math.floor((left + right) / 2);
var dataPath = this.data[mid].sortPath;
if (this.data[mid].path == origPath || this.data[mid].path + "/" == origPath || this.data[mid].path == origPath + "/") {
return mid;
} else if (dataPath == path || dataPath + "\x01" == path || dataPath == path + "\x01") {
break;
} else if (path < dataPath) {
right = mid - 1;
} else if (path > dataPath) {
left = mid + 1;
}
}
for (var x = 0; x < this.data.length; ++x) { // last ditch effort b/c of we have to account for case
if (this.data[x].path == origPath || this.data[x].path + "/" == origPath || this.data[x].path == origPath + "/") {
return x;
}
}
return -1;
},
cdup : function() {
var parentIndex = this.getParentIndex(this.selection.currentIndex);
if (parentIndex != -1) {
this.selection.select(parentIndex);
}
},
updateViewAfter : false,
changeDir : function(path) {
if (!gFtp.isConnected || gFtp.isListing()) {
if (!gFtp.isConnected) {
gTreeSyncManager = null;
}
return;
}
gRemotePath.value = path;
if (this.data.length == 0) { // if dirTree is empty
var oldRowCount = this.rowCount;
this.data = new Array();
this.rowCount = 0;
this.treebox.rowCountChanged(0, -oldRowCount);
this.data.push({ open : false, // restart the tree
empty : false,
hasNext : false,
parentIndex : -1,
children : null,
path : "/",
leafName : "/",
parent : "",
level : 0,
sortPath : "/".replace(/\x2f/g, "\x01").toLowerCase() });
this.rowCount = 1;
this.treebox.rowCountChanged(0, 1);
}
// error checking here for correct values in path
gRemotePath.value = gRemotePath.value.replace(/\x5c/g, "/"); // shouldn't have backslashes
if (gRemotePath.value != '/' && gRemotePath.value.charAt(gRemotePath.value.length - 1) == '/') {
gRemotePath.value = gRemotePath.value.substring(0, gRemotePath.value.length - 1); // cannot end with '\' ruins levels in dir tree
}
if (gRemotePath.value.charAt(0) != '/') { // has to start with '/'
gRemotePath.value = '/' + gRemotePath.value;
}
for (var x = 0; x < this.data.length; ++x) { // open parent directories til we find the directory
for (var y = this.data.length - 1; y >= x; --y) {
if (gRemotePath.value.indexOf(this.data[y].path) == 0) {
x = y;
break;
}
}
if (gRemotePath.value.indexOf(this.data[x].path) == 0) {
var dirty = false;
for (var z = 0; z < this.dirtyList.length; ++z) {
if (this.dirtyList[z] == this.data[x].path) {
dirty = true;
break;
}
}
if (this.data[x].open && dirty) {
this.ignoreSelect = true;
this.toggleOpenState(x);
this.ignoreSelect = false;
}
if (this.data[x].empty && dirty) {
this.data[x].empty = false;
this.treebox.invalidateRow(x);
}
if (!this.data[x].open && !this.data[x].empty && gRemotePath.value != this.data[x].path) {
gRemotePath.value = this.data[x].path;
gRemotePathFocus = this.data[x].path;
this.selection.select(x);
gFtp.list(this.data[x].path, "remoteDirTree.toggleOpenState2(" + x + ");remoteDirTree.changeDir('" + path.replace(/'/g, "\\'") + "')", false);
return;
} else if (gRemotePath.value == this.data[x].path) {
gRemotePathFocus = gRemotePath.value; // directory approved
gFormHistory.addEntry(gRemotePath.getAttribute("autocompletesearchparam"), gRemotePath.value);
if (!this.data[x].open && !this.data[x].empty && x == 0) {
this.updateViewAfter = true;
this.toggleOpenState(x);
} else {
remoteTree.updateView();
this.readjustHorizontalPosition(this.selection.currentIndex);
}
if (gTreeSync && !gTreeSyncManager) {
treeSyncManager(false);
} else {
gTreeSyncManager = false;
}
return;
}
}
}
if (gTreeSyncManager) {
gTreeSyncManager = false;
gRemotePath.value = gRemotePathFocus;
remoteTree.updateView();
return;
}
this.dontPanic();
},
dontPanic : function() { // we haven't found the directory in the conventional
gRemotePathFocus = gRemotePath.value; // sense: don't freak out, just create directories
this.treebox.rowCountChanged(0, -this.rowCount); // above as if it were there and list
this.rowCount = 0;
this.data = new Array();
this.data.push({ open : true, // restart the tree
empty : false,
hasNext : false,
parentIndex : -1,
children : null,
path : "/",
leafName : "/",
parent : "",
level : 0,
sortPath : "/".replace(/\x2f/g, "\x01").toLowerCase() });
var paths = gRemotePath.value.split("/");
var parentDir = "/";
for (var x = 0; x < paths.length; ++x) {
if (paths[x] != "") {
var path = gFtp.constructPath(parentDir, paths[x]);
this.data.push({ open : true,
empty : false,
hasNext : false,
parentIndex : -1,
children : null,
path : path,
leafName : paths[x],
parent : parentDir,
level : path.match(/\x2f/g).length,
sortPath : path.replace(/\x2f/g, "\x01").toLowerCase() });
parentDir += (parentDir != "/" ? "/" : "") + paths[x];
}
}
this.data[this.data.length - 1].open = false; // make last directory closed
this.updateParentIndices();
this.rowCount = this.data.length; // update tree
this.treebox.rowCountChanged(0, this.rowCount);
this.selection.select(this.rowCount - 1);
this.updateViewAfter = true; // open up the last directory
this.toggleOpenState(this.data.length - 1);
},
select : function(event) {
if (this.ignoreSelect) {
return;
}
var index = this.selection.currentIndex;
if (index >= 0 && index < this.data.length && this.data[index].path != gRemotePath.value) {
this.changeDir(this.data[index].path);
}
},
click : function(event) { // this is a special case: if we want the search to go away
var index = this.selection.currentIndex;
if (index >= 0 && index < this.data.length && (this.data[index].path == gRemotePath.value && remoteTree.searchMode)) {
this.changeDir(this.data[index].path);
}
},
keyPress : function(event) {
if (event.keyCode == 8) { // backspace
this.cdup();
} else if (event.keyCode == 116) { // F5
event.preventDefault();
remoteTree.refresh();
}
},
canDrop : function(index, orient) {
if (!gFtp.isConnected || index == -1 || orient != 0 || !dragObserver.origin) {
return false;
}
if (dragObserver.origin == 'remotetreechildren') { // can't move into a subdirectory of itself
for (var x = 0; x < remoteTree.rowCount; ++x) {
var remotePath = remoteTree.data[x].path;
var dataPathSlash = this.data[index].path + (this.data[index].path.charAt(this.data[index].path.length - 1) != "/" ? "/" : '');
var remotePathSlash = remotePath + (remotePath.charAt(remotePath.length - 1) != "/" ? "/" : '');
if (remoteTree.selection.isSelected(x) && ((dataPathSlash.indexOf(remotePathSlash) == 0 && remoteTree.data[x].isDirectory())
|| this.data[index].path ==
remotePath.substring(0, remotePath.lastIndexOf('/') ? remotePath.lastIndexOf('/') : 1))) {
return false;
}
}
}
return true;
},
drop : function(index, orient) {
if (dragObserver.origin == 'remotetreechildren') {
remoteTree.cut();
var self = this;
var path = this.data[index].path;
var func = function() { remoteTree.paste(path); };
gFtp.list(this.data[index].path, func, true);
} else if (dragObserver.origin == 'localtreechildren') {
var anyFolders = false;
for (var x = 0; x < localTree.rowCount; ++x) {
if (localTree.selection.isSelected(x) && localTree.data[x].isDirectory()) {
anyFolders = true;
break;
}
}
var path = this.data[index].path;
if (anyFolders && this.data[index].path != gRemotePath.value) {
var self = this;
var remotePath = gRemotePath.value;
var func = function() { self.dropCallback(path, remotePath); };
ftpObserver.extraCallback = func;
}
var self = this;
var transferObj = new transfer();
transferObj.remoteRefresh = gRemotePath.value;
var func = function() { transferObj.start(false, '', '', path); };
gFtp.list(this.data[index].path, func, true);
} else if (dragObserver.origin == 'external') {
var anyFolders = false;
for (var x = 0; x < dragObserver.externalFiles.length; ++x) {
if (dragObserver.externalFiles[x].isDirectory()) {
anyFolders = true;
break;
}
}
if (anyFolders && this.data[index].path != gRemotePath.value) {
var self = this;
var path = this.data[index].path;
var remotePath = gRemotePath.value;
var func = function() { self.dropCallback(path, remotePath); };
ftpObserver.extraCallback = func;
}
var transferObj = new transfer();
transferObj.remoteRefresh = gRemotePath.value;
for (var x = 0; x < dragObserver.externalFiles.length; ++x) {
var droppedFile = dragObserver.externalFiles[x];
var fileParent = droppedFile.parent ? droppedFile.parent.path : "";
this.dropHelper(transferObj, droppedFile, fileParent, index);
if (transferObj.cancel) {
break;
}
}
}
},
dropHelper : function(transferObj, droppedFile, fileParent, index) {
var self = this;
var remotePath = this.data[index].path;
var func = function() { transferObj.start(false, droppedFile, fileParent, remotePath); };
gFtp.list(this.data[index].path, func, true);
},
dropCallback : function(newParent, remotePath) {
var refreshIndex = this.indexOfPath(newParent);
if (refreshIndex != -1) {
if (this.data[refreshIndex].open) {
var self = this;
var path = remotePath;
var dropCallback2 = function() { self.dropCallback2(path); };
this.extraCallback = dropCallback2;
this.toggleOpenState(refreshIndex, true); // close it up
this.data[refreshIndex].children = null; // reset its children
this.toggleOpenState(refreshIndex); // and open it up again
return;
} else {
this.data[refreshIndex].children = null; // reset its children
this.data[refreshIndex].empty = false;
this.treebox.invalidateRow(refreshIndex);
}
var refreshIndex2 = this.indexOfPath(remotePath);
if (refreshIndex2 == -1) {
this.changeDir(remotePath);
return;
} else {
this.selection.select(refreshIndex2);
}
} else {
this.addDirtyList(newParent);
}
},
dropCallback2 : function(returnDir) {
var refreshIndex2 = this.indexOfPath(returnDir);
if (refreshIndex2 == -1) {
this.changeDir(returnDir);
return;
} else {
this.selection.select(refreshIndex2);
}
}
};